<template xmlns="http://www.w3.org/1999/html">
  <div class="uploaded-files">
    <div v-for="(item, idx) in valueModel" :key="idx" class="file-container">
      <!-- 图片类型：显示图片预览 -->
      <div v-if="item.type === 'image'" class="image-wrapper" style="font-size: small">
        <el-image lazy :src="item.src" :preview-src-list="[item.src]" fit="cover"
                  style="width: 80px; height: 80px;"></el-image>
        <i class="el-icon-delete delete-icon" @click="removeFile"></i>
      </div>

      <!-- 非图片类型：显示文件图标 -->
      <div v-else class="file-wrapper" style="padding-top: 20px;">
        <i class="file-icon el-icon-document"></i>
        <br/>
        <span class="sea-filename">{{ item.name }}</span>
        <i class="delete-icon el-icon-delete" @click="removeFile"></i>
      </div>
    </div>

    <div v-show="canUpload" class="file-wrapper" style="padding-top: 16px;">
      <div @click="$refs.input.click()">
        <input type="file" ref="input" :accept="accept" style="display: none" @change="onchange" multiple>
        <p><i class="el-icon-upload"></i></p>
        <p style="font-size: small">点击上传</p>
      </div>
    </div>
  </div>
</template>
<script>
/* eslint-disable */
import Layers from "@/lang/layers";
import FileUtils from "@/lang/commons/file-utils";

/**
 * 文件上传接口
 *
 * @param file {File}
 */
const default_upload = (file) => {
    return Promise.resolve({name: file.name, size: file.size, ref: file});
}

/**
 * 文件移除接口
 *
 * @param item
 * @returns {Promise<void>}
 */
const default_remove = (item) => {
    return Promise.resolve();
}

/**
 * 图片上传
 *
 * 图片上传组件，因为图片涉及到预览的问题，相对于其它文件，图片使用频率也是最高的，
 * 因此单独封装，方便后期功能扩展。
 *
 * 注意这个不是根据 el-upload 封装的，虽然 el-upload 的功能很强，但是封装的内容太多，
 * 使用的时候，如果参数过多，Vue 数据联动，很容易发生界面跳动闪烁。
 *
 * 这个组件代码非常简单，核心代码包含注释只有三百多行，大幅度减轻代码设计，界面响应流畅。
 */
export default {
    name: "SeaFileUploader"
    , props: {
        value: {type: Array, default: Layers.array}
        // 文件数量上限
        , limit: {type: Number, default: 6}
        // 可接受的文件类型
        , accept: {type: String, default: '*'}
        // 上传配置选择
        , plugin: {type: String, default: 'image'}
        // 文字提示
        , placeholder: {type: String, default: ''}

        // 文件上传函数，也可以等到最后统一上传
        , upload: {type: Function, default: default_upload}
        // 文件上传函数，也可以等到最后统一上传
        , remove: {type: Function, default: default_remove}
    }, model: {
        //需要定义哪一个props可以用v-model绑定属性
        prop: 'value',
        //声明一个事件，调用之后，就会改变父级容器的值
        event: 'handlerValueChange'
    }, data() {
        return {
            // 值模型，任何时候都不允许为空，避免VUE联动失效
            valueModel: []
            // 文件列表
            , fileList: []
            // 数据上传中
            , loading: false
        }
    }, computed: {
        canUpload: function () {
            return this.valueModel.length < this.limit;
        }
    }, watch: {
        value: {
            handler: function (val) {
                if(val !== undefined){
                    this.wrapFileItem(val);
                    this.valueModel = this.value;
                }
            },
            immediate: true
        }
    }, methods: {
        /**
         * 值改变事件
         */
        trigger: function (val) {
            //侦听到setter()事件，将值传递回父级组件
            this.$emit('handlerValueChange', val);
            this.$emit('change', val);
        }
        /**
         * 格式化入参，注意图片需要设置可供预览的 src 属性
         * @param list -
         */
        , wrapFileItem: (list) => {
            for (let i = 0, len = list.length; i < len; i++) {
                const item = list[i];
                const ext = FileUtils.getExtension(item.name);
                item.icon = FileUtils.getFileIcon(ext);
                item.type = FileUtils.getFileType(ext);
                if(item.type === 'image'){
                    if(item.src === undefined){
                        item.src = item.url;
                    }
                }
            }
        }
        /**
         * 移除图片
         *
         * @param idx 文件序号
         */
        , removeFile: function (idx) {
            let list = this.fileList;
            let item = list[idx];
            list.splice(idx, 1);

            this.onChange(this.fileList);

            // 即使移除失败，也不能影响主要业务
            this.remove(item);
        }

        /**
         * 查看上传的文件
         *
         * @param item
         */
        , previewFile(item) {
            if (item.url !== undefined) {
                window.open(item.url);
            }
        }
        /**
         * 文件转为 base64 字符串
         *
         * @param event change-event
         */
        , async onchange(event) {
            const files = event.target.files;
            if (files.length > 0) {
                for (let i = 0, len = files.length; i < len; i++) {
                    const file = files[i];
                    const ext = FileUtils.getExtension(file.name);
                    const icon = FileUtils.getFileIcon(ext);
                    const type = FileUtils.getFileType(ext);

                    const item = {icon: icon, url: '', src: '', name: file.name, ref: file, type: type};
                    if (type === 'image') {
                        item.src = await FileUtils.convertFileToBase64(file)
                    }

                    this.valueModel.push(item);
                }
                event.target.value = '';
            } else {
                this.valueModel.length = 0;
            }
            this.trigger(this.valueModel);
        }
    }
}
</script>
<style scoped>
.uploaded-files {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 10px;
}

.file-wrapper {
    width: 80px;
    height: 80px;
    text-align: center;
    background-color: #f5f7fa;
    border-radius: 4px;
    border: 1px solid #ebeef5;
    transition: all 0.2s;
    color: #409eff;
    line-height: normal;
    font-weight: normal;
}


.image-wrapper {
    width: 80px;
    height: 80px;
    text-align: center;
    background-color: #f5f7fa;
    border-radius: 4px;
    border: 1px solid #ebeef5;
    transition: all 0.2s;
    color: #409eff;
    line-height: normal;
    font-weight: normal;
}

.file-wrapper p {
    line-height: normal;
    margin: 0;
    padding: 0;
}

.file-wrapper:hover {
    background-color: #e9eef3;
}

.file-container {
    position: relative;
    width: 80px;
    height: 80px;
}

.file-icon {
    font-size: 22px;
}

.file-name {
    max-width: 70px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: center;
    font-size: 12px;
    color: #606266;
}

.sea-filename {
    font-size: 10px;
    line-height: normal;
    display: inline-block;
    width: 64px; /* 设置固定宽度 */
    white-space: nowrap; /* 禁止换行 */
    overflow: hidden; /* 隐藏溢出内容 */
    direction: rtl; /* 从右到左的文本方向 */
    text-overflow: ellipsis; /* 显示省略号 */
}

.delete-icon {
    position: absolute;
    top: -8px;
    right: -8px;
    color: white;
    background-color: rgba(245, 108, 108, 0.8);
    border-radius: 50%;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 10;
    transition: all 0.2s;
    box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
}

.delete-icon:hover {
    background-color: #f56c6c;
    transform: scale(1.1);
}
</style>